#include "Texture.h"
#include "CGameApp.h"
#include "CEntity.h"

#include <windows.h>
#include <cmath>
#include <ctime>
#include <sstream>
//#include <stdio.h>		// Header File For Standard Input/Output ( NEW )
#include <string>
//#include <GL/glut.h>


#include <iostream>
using namespace std;


float VIEW_HEIGHT = 20.0f;
float VIEW_WIDTH  = -1.0f;
//const float PI    = 3.14159;
static float framerate = 0.0f;
static float fmax = 0.0f;
static float fmin = 999.0f;
static float keypressed = 80.0f;

void DrawCircle( float cx, float cy, float r );
void DrawDisk( float cx, float cy, float r );
void ScreenToView( int sx, int sy, float& vx, float& vy );
void DrawString( float x, float y, std::string s )
{
	glRasterPos2f(x,y);
	for(size_t i = 0; i < s.length(); ++i )
		glutBitmapCharacter( GLUT_BITMAP_TIMES_ROMAN_24, s[i] );
}

CGameApp Game = CGameApp();
int mousex, mousey;
float fx, fy;


void OnArrowPress( int key, int x, int y )
{
	Game.ArrowState[key] = true;
	//cout << "key = " << key << endl;
}

void OnArrowRelease( int key, int x, int y )
{
	Game.ArrowState[key] = false;
}

void OnKeyPress( unsigned char key, int x, int y )
{
	if( key == 'z' )
	{
		keypressed -= 15.0f * Game.DeltaTime;
	}
	if( key == 'x' )
	{
		keypressed += 15.0f * Game.DeltaTime;
	}
	Game.KeyState[key] = true;
	switch( key )
	{
	case 9:
		//cout << "tab pressed" << endl;
		break;
	case 32:	//space bar
		break;
	case 27:	//esc key
		exit(0);
		break;
	}
	//cout << true << " " << Game.KeyState[key] << endl;
	//if (glutGetModifiers() == GLUT_ACTIVE_SHIFT) 
	//{  
	//	cout << "SHIFT pressed.";  
	//}  
	//cout << key << endl;
	//int keay = key;
	//cout << keay << endl;
	//if( key == '\t' )
	//{ 
	//	int a = '\t';
	//	cout << "success" << " " << a << " " << endl; 
	//}

}

void OnKeyRelease( unsigned char key, int x, int y )
{
	//cout << "key release called on " << Game.KeyState[key] << endl;
	Game.KeyState[key] = false;
	//cout << "now it's " << Game.KeyState[key] << endl;
}

void OnMouseClick( int button, int state, int x, int y )
{
	Game.KeyState[32] = !state;
	//Game.Player->FireBullet();
	mousex = x;
	mousey = y;
	float newx;
	float newy;
	ScreenToView( mousex, mousey, newx, newy );
	//Game.Player[0]->SetPos( newx, newy );
	//ScreenToView( x, y, fx, fy );
	//Game.Player->SetFaceAngle( fx, fy );
	for( int i = 0; i < Game.NumEnemies; i++ )
	{
		//Game.Enemy[i]->SetFaceAngle( fx,fy );
		//Game.Enemy[i]->RotateFaceAngleBy( 180.0f );
	}
}

void InMotion( int x, int y )//when a mouse button is down
{
	int s = Game.NumPlayers-1;
	Game.Player[s]->FireBullet();
	float prex = mousex;
	float prey = mousey;
	mousex = x;
	mousey = y;
	if( prex > mousex )
	{
		//rotateleft
		Game.Player[s]->RotateFaceAngleBy( Game.DeltaTime * Game.Player[s]->GetRotateSpeed()*360 );
	}
	if( prex < mousex )
	{
		//rotateright
		Game.Player[s]->RotateFaceAngleBy( Game.DeltaTime * -Game.Player[s]->GetRotateSpeed()*360 );
	}

	//ScreenToView( x, y, fx, fy );
	//Game.Player->SetFaceAngle( fx, fy );
}

void InPassiveMotion( int x, int y ) //when the mouse buttons are up
{
	int s = Game.NumPlayers-1;
	float prex = 250;//mousex;
	float prey = 250;//mousey;
	mousex = x;
	mousey = y;
	if( prex > mousex )
	{
		//rotateleft
		//Game.Player[s]->RotateFaceAngleBy( Game.DeltaTime * Game.Player[s]->GetRotateSpeed()*360 );
	}
	if( prex < mousex )
	{
		//rotateright
		//Game.Player[s]->RotateFaceAngleBy( Game.DeltaTime * -Game.Player[s]->GetRotateSpeed()*360 );
	}
	//glutSetCursor( GLUT_CURSOR_NONE );
	////SetCursorPos( 412+250, 40+250 );
	//if( prex != mousex || prey != mousey )
	//{
		//glutWarpPointer( 250, 250 );
	//}
	//ScreenToView( x, y, fx, fy );
	//for( int i = 0; i < Game.NumEnemies; i++ )
	//{
	//	Game.Enemy[i]->SetFaceAngle( Game.Player->GetPosX(),Game.Player->GetPosY() );
	//	Game.Enemy[i]->RotateFaceAngleBy( 180.0f );
	//}

	//float fx, fy;
	//ScreenToView( x, y, fx, fy );
	//fx = fx - Game.Player->GetPosX();
	//fy -= Game.Player->GetPosY();
	////sqrt( fx*fx + fy*fy );
	//Game.Player->SetFaceAngleTo( atan( fy/fx )*57.2958f );
}

void OnIdle()
{
	//game loop
	//ScreenToView( mousex, mousey, fx, fy );
	//for( int i = 0; i < Game.NumEnemies; i++ )
	//{
	//	Game.Enemy[i]->SetFaceAngle( Game.Player->GetPosX(),Game.Player->GetPosY() );
		//Game.Enemy[i]->RotateFaceAngleBy( 180.0f );
	//}
//	glutWarpPointer( 250, 250 );
	Game.Update();
	//new code
	//glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();
	static float xc = 0;
	static float yc = 0;
	static float rcf = 2;
	//gluLookAt( 0, 0, 0.01,
	//	       0, 0, -0.01,
	//		   cosf(xc), sinf(xc), 0);
	static float camerax,cameray,cameraz;
	static float prevcamerax;
	prevcamerax = camerax;
	if( Game.NumPlayers > 1 )
	{
		if( Game.Player[0]->GetAlive() == true && Game.Player[1]->GetAlive() == true )
		{
			camerax = 0.5f * (Game.Player[0]->Pos.x - Game.Player[1]->Pos.x) + Game.Player[1]->Pos.x;
			cameray = 0.5f * (Game.Player[0]->Pos.y - Game.Player[1]->Pos.y) + Game.Player[1]->Pos.y;
			cameraz = sqrt((Game.Player[0]->Pos.x - Game.Player[1]->Pos.x)*(Game.Player[0]->Pos.x - Game.Player[1]->Pos.x)+
							(Game.Player[0]->Pos.y - Game.Player[1]->Pos.y)*(Game.Player[0]->Pos.y - Game.Player[1]->Pos.y));
		}
		if( Game.Player[0]->GetAlive() == true && Game.Player[1]->GetAlive() == false )
		{
			camerax = Game.Player[0]->Pos.x;
			cameray = Game.Player[0]->Pos.y;
			cameraz = 11.925f+5;
		}
		if( Game.Player[0]->GetAlive() == false && Game.Player[1]->GetAlive() == true )
		{
			camerax = Game.Player[1]->Pos.x;
			cameray = Game.Player[1]->Pos.y;
			cameraz = 11.925f+5;
		}
		if( Game.Player[0]->GetAlive() == false && Game.Player[1]->GetAlive() == false )
		{

		}
	}
	else
	{
		//if( 
		camerax = Game.Player[0]->Pos.x;
		cameray = Game.Player[0]->Pos.y;
		cameraz = 11.925f+5;
	}
	//cameray = -5;
	static float mincamerax = -100;//camerax - 5;//-29.0f;
	static float maxcamerax = 100.0f;
	static float somex = 3.0f;

	if( Game.KeyState['x'] == true )
	{
		//cout << mincamerax << " " << camerax << " " << camerax - mincamerax << endl;//" " << Game.Player[0]->Pos.x << endl;
	}
	if( camerax < mincamerax ) { camerax = mincamerax; }
	if( camerax > maxcamerax ) { camerax = maxcamerax; }
	if( camerax > prevcamerax ) 
	{
		//mincamerax = camerax;
	}

	if( cameraz > 40 )      { cameraz = 40.0f; }
	if( cameraz < 11.925f )      { cameraz = 11.925f; }
	cameraz = 18;
	gluLookAt( cos(xc)*rcf + camerax,  sin(xc)*rcf + cameray, cameraz,
			   cos(xc)*rcf + camerax,  sin(xc)*rcf + cameray, -cameraz,//Game.Player[0]->Pos.x, Game.Player[0]->Pos.y,  0,
			   0,  1,  0);
	//glMatrixMode( GL_MODELVIEW );
	//cout << xc << endl;
	rcf -= 1.0f * Game.DeltaTime;
	if( rcf < 0 ) { rcf = 0; }
	xc += 40.0f * Game.DeltaTime;
	yc += 3.99f * Game.DeltaTime;
	//gluLookAt(		Game.Player[0]->Pos.x, Game.Player[0]->Pos.y, 11.925,
	//				Game.Player[0]->Pos.x, Game.Player[0]->Pos.y,	   0,
	//				0, 1, 0);
	//end new code
	if(Game.KeyState['r'] == true)
		cout << fmax << " " << framerate << " " << fmin << endl;
	if(Game.KeyState['h'] == true)
	{ rcf = 0.3f; xc = (rand()%100)/100.0f * 6.28f; }

	glutPostRedisplay();
}

void Reshape(int w, int h)
{
	float aspectRatio = float(w)/h;
	VIEW_WIDTH        = aspectRatio*VIEW_HEIGHT;
	glViewport( 0, 0, w, h);
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();
	gluPerspective(80.0f, aspectRatio, 1.0, 100.0);
	//glOrtho( Game.Player[0]->GetPosX()-5 , Game.Player[1]->GetPosX()+5,
	//		 Game.Player[0]->GetPosY()-5 , Game.Player[1]->GetPosY()+5,
	//		 -100 , 100 );
	//glOrtho( -VIEW_WIDTH/2, VIEW_WIDTH/2, 
	//	     -VIEW_HEIGHT/2, VIEW_HEIGHT/2, 
	//		 -100.0, 100.0);
	glMatrixMode( GL_MODELVIEW );
}


void Display()
{
	static float lasttime = glutGet( GLUT_ELAPSED_TIME );
	static int ticks = 0;

	//static float framerate = 0.0f;
	ticks += 1;
	float time = glutGet( GLUT_ELAPSED_TIME );
	//time - lasttime = 0012
	//1000 / time-lasttime = framespersecond
	//framerate = 1000/(time - lasttime);
	//lasttime = time;
	if( (time - lasttime) > 1000 )
	{
		framerate = ticks;
		lasttime = time;
		ticks = 0;
		if( framerate>fmax ) {fmax = framerate;}
		if( framerate<fmin ) {fmin = framerate;}
	}
	glClear( GL_COLOR_BUFFER_BIT );
	//float t = glutGet( GLUT_ELAPSED_TIME ) * 0.001;
	//gb.drawBoard();
	glBindTexture( GL_TEXTURE_2D, 0 );
	glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
	static std::ostringstream ss;
	ss.str("");
	ss << framerate << " " << Game.Player[0]->FriendLevel;//Game.EnemyWave->EnemiesRemaining;// << " " << Game.Player->GetHealth();//;//Game.EnemyWave->EnemiesRemaining;//framerate;
	//static std::ostringstream info;
	//info.str("");
	//info << Game.Player[0]->GetVelX() << " " << Game.Player[0]->GetVelY();
	//static std::ostringstream corners;
	//corners.str("");
	//corners << Game.Player[0]->bottomleftx << " " << Game.Player[0]->bottomlefty;
	//DrawString( -VIEW_WIDTH/2, VIEW_HEIGHT/2-1.0f, ss.str() );
	
	//std::ostringstream mousePos;
	//mousePos << "mousePos = " << mousex << " , " << mousey;
	//DrawString( VIEW_WIDTH/2 - 10 , VIEW_HEIGHT/2-1.0f, mousePos.str() );

//	std::ostringstream SA;
//	SA << "spreadAngle = " << Game.Player->SpreadAngle;
//	DrawString( VIEW_WIDTH/2 - 11 , VIEW_HEIGHT/2-1.0f, SA.str() );

//	std::ostringstream mousePos;
//	mousePos << "mousePos = " << gb.MouseX << " , " << gb.MouseY;
//	DrawString( VIEW_WIDTH/2 - 10 , VIEW_HEIGHT/2-1.0f, mousePos.str() );
	//Reshape( 1366, 768 );//VIEW_WIDTH, VIEW_HEIGHT );// 5,40 );
	Game.Render();
	DrawString( -VIEW_WIDTH/2, VIEW_HEIGHT/2-1.0f, ss.str() );
	//DrawString( -VIEW_WIDTH/2, VIEW_HEIGHT/2-3.0f, info.str() );
	//DrawString( -VIEW_WIDTH/2, VIEW_HEIGHT/2-4.0f, corners.str() );
	//std::ostringstream t;
	//t.str("");
	//t << "spacebackground" << 2 << ".tga";
	//= "mystring";// << " is stupid";
	//t += 2;
	//DrawString( 0, 0, t.str() );
	//std::ostringstream playerhealth;
	//playerhealth <<  Game.Player->GetHealth();
	//glBindTexture( GL_TEXTURE_2D, 0 );
	//glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
	//DrawString( Game.Player->GetPosX()-Game.Player->GetRadius()*0.5f, Game.Player->GetPosY()-Game.Player->GetRadius()*0.5f , playerhealth.str() );
//	std::ostringstream blockinfo;
//	blockinfo << Game.Block[1]->GetPosX() - Game.Block[1]->GetRadius() << " , "
//			  << Game.Block[1]->GetPosX() << " , " << Game.Block[1]->GetPosX() + Game.Block[1]->GetRadius();
//	glBindTexture( GL_TEXTURE_2D, 0 );
//	glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
//	DrawString( -VIEW_WIDTH/2, VIEW_HEIGHT/2-2.0f, blockinfo.str() );

	//glBegin( GL_LINES );
	//	glColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
	//	glVertex2f( -1.0f, 0.0f );
	//	glVertex2f( 1.0f, 0.0f );

	//	glVertex2f( 0.0f, -1.0f );
	//	glVertex2f( 0.0f, 1.0f );

	//glEnd();
	glutSwapBuffers();
};

#define NEW_GAME 0
#define KEEP_GOING 1
#define RETURN_TO_MENU 2
#define END_GAME 3

void processMenuEvents( int option )  //this needs to be updated
{
	static float playerx = Game.Player[0]->GetPosX();
	static float playery = Game.Player[0]->GetPosY();
switch( option )
	{
	case NEW_GAME:
		Game.Player[0]->SetPosX( playerx );
		Game.Player[0]->SetPosY( playery );
		//8 and 10 are the limit with one color and a 200 sized array
		//gb.createLevel( 3000, 11 );// (rand() % (gb.getBlocksHigh() - 3)) , (rand() % 10) );
		//gb.setScore( 0 );
		//gb.setComboMultiplier(1);
		//gb.createGamePiece();
		//gb.addPieceToBoard( gb.LivePiece );
		//gb.findShadow( 0, 1 );
		//gb.setItemFalling( GAME_PIECE );
		//gb.setFallTimer( 0.0f );
		break;
	case KEEP_GOING:
		break;
	case RETURN_TO_MENU:
		//gb.setGameScreen( TITLE_SCREEN );
		break;
	case END_GAME:
		exit(0);
		break;
	}
}

void createGlutMenus()
{
	int menu;
	//create the menu
	menu = glutCreateMenu( processMenuEvents );
	//add menu events
	glutAddMenuEntry( "New Game", NEW_GAME );
	glutAddMenuEntry( "Keep Going", KEEP_GOING );
	glutAddMenuEntry( "Return to Menu", RETURN_TO_MENU );
	glutAddMenuEntry( "End Game", END_GAME );
	//attach the menu
	glutAttachMenu( GLUT_RIGHT_BUTTON );

}

int main( int argc, char** argv )
{
	//cout << "GLUT_LEFT_BUTTON = " << GLUT_LEFT_BUTTON << endl;
	//cout << "GLUT_RIGHT_BUTTON = " << GLUT_RIGHT_BUTTON << endl;
	//cout << "GLUT_MIDDLE_BUTTON = " << GLUT_MIDDLE_BUTTON << endl;
	//cout << "GLUT_UP = " << GLUT_UP << endl;
	//cout << "GLUT_DOWN = " << GLUT_DOWN << endl;

//	cout << "cos(90deg)" << cos( PI/2 ) << endl;
//	cout << "cos(135)"	 << cos( 3*PI/4 ) << endl;
//	cout << "cos(225)"   << cos( 5*PI/4 ) << endl;
//	cout << "cos(270)"	 << cos( 3*PI/2 ) << endl;
//	cout << (2.0f*PI)/360.0f << " = degrees to radians " << endl;
//	cout << 360.0f/(2.0f*PI) << " = radians to degrees " << endl;

	//int * myArray = new int[45];
	//delete [] myArray;
	//int mine[5];
	//mine[0] = 4;
	//mine[1] = 6;
	//void (*f[2])(void) = { Display, OnIdle };
	
	//srand( glutGet( GLUT_ELAPSED_TIME ) );
	//list< int > myints;
	//myints.push_back(1);
	//myints.push_back(2);
	//myints.push_back(3);
	//myints.push_back(4);
	//cout << myints.empty() << endl;
	//list<int>::iterator i;
	//for( i = myints.begin(); i != myints.end(); i++ )
	//{
	//	cout << *i << " ";
	//	if( *i == 2 )
	//	//{ myints.remove( *i ); i--;}
	//	cout << *i << endl;
	//}
	//myints.clear();
	//cout << myints.empty() << endl;
	





	glutInit(&argc, argv);
	glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
	glutInitWindowPosition(200, 20);
	glutInitWindowSize(1024, 600);
	glutCreateWindow("A-Twee-Dilemma");
	createGlutMenus();
	glClearColor( 0.0f,0.0f,0.0f,1);
	//glClearColor( 0.4f, 0.2f, 0.4f, 0.4f );
	glutSetCursor( GLUT_CURSOR_NONE );

	glutReshapeFunc( Reshape );
	glutDisplayFunc( Display );
	glutKeyboardFunc( OnKeyPress );
	glutKeyboardUpFunc( OnKeyRelease ); 
	glutSpecialFunc( OnArrowPress );
	glutSpecialUpFunc( OnArrowRelease );
	glutMouseFunc( OnMouseClick );
	glutMotionFunc( InMotion );
	glutPassiveMotionFunc( InPassiveMotion );
	glutIdleFunc( OnIdle );

	//glutFullScreen();

	Game.InitializeGame();
	Reshape(5,40);
	//f[0]();//0 is display
	glEnable(GL_BLEND); 
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glMatrixMode(GL_MODELVIEW);
	//glTexParameterf( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER, GL_NEAREST );
	glutMainLoop();
	return 0;
};


void ScreenToView( int sx, int sy, float& vx, float& vy )
{
	int ScreenWidth  = glutGet( GLUT_WINDOW_WIDTH );
	int ScreenHeight = glutGet( GLUT_WINDOW_HEIGHT );

	vx = +float(sx) * VIEW_WIDTH/ScreenWidth - VIEW_WIDTH/2;
	vy = -float(sy) * VIEW_HEIGHT/ScreenHeight + VIEW_HEIGHT/2;
}

void DrawCircle( float cx, float cy, float r)
{
	const float PI = 3.14159f;
	float nextstep = 2.0f*PI/32.0f;

	glBegin( GL_LINE_LOOP );
	for( float t = 0.0f; t < PI*2; t+= nextstep )
	{
		float x = r * cosf( t ) + cx;
		float y = r * sinf( t ) + cy;
		glVertex2f( x, y );
	}
	glEnd();
}

void DrawDisk( float cx, float cy, float r )
{
	const float PI = 3.14159f;
	float nextstep = 2.0f*PI/32.0f;

	glBegin( GL_TRIANGLE_FAN );
	for( float t = 0.0f; t < PI*2; t+= nextstep )
	{
		float x = r * cosf( t ) + cx;
		float y = r * sinf( t ) + cy;
		glVertex2f( x, y );
	}
	glEnd();
}
